import 'dart:async';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/cupertino.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:sleep/db/export.dart';
import 'package:sleep/provider/db_provider.dart';
import 'package:sleep/single/analyze/base_analyze.dart';
import 'package:sleep/single/analyze/fatigue_analyze.dart';
import 'package:sleep/single/analyze/pluse_analyze.dart';
import 'package:sleep/single/analyze/sleep_analyze.dart';
import 'package:sleep/provider/blue/blue_provider.dart';
import 'package:sleep/provider/digital_filter_provider.dart';
import 'package:sleep/single/filter/digital_filter.dart';
import 'package:sleep/single/filter/multiple_filter.dart';
import 'package:sleep/single/filter/outlier_filter.dart';
import 'package:sleep/single/filter/real_filter.dart';
import 'package:sleep/single/point_model.dart';
import 'package:sleep/config.dart';

class WaveDataNotifier extends ChangeNotifier {
  final Stream<List<double>> stream;
  final BaseAnayze analyze;
  StreamSubscription? _lisenData;
  bool needSave = false;

  Timer? _timer;
  WaveDataNotifier(this.stream, this.analyze) {
    config();
  }

  List<FlSpot> get spots {
    List<FlSpot> flspots = [];
    for (int i = 0; i < kPointKLength; i++) {
      final index = analyze.points.length - i - 1;
      if (index > 0) {
        flspots
            .add(FlSpot((kPointKLength - i).toDouble(), analyze.points[index]));
      }
    }
    return flspots;
  }

  changeSave(
    bool save, {
    bool? fatigue,
    bool? sleep,
  }) {
    needSave = save;
    if (save) {
      if (sleep == true) Export.share().createSleep();
      if (fatigue == true) Export.share().createFatigue();
    } else {
      if (sleep == true) Export.share().finshSleep();
      if (fatigue == true) Export.share().finishFatigue();
    }
    notifyListeners();
  }

  double? get rt => analyze.points.isEmpty ? null : analyze.points.last;
  List<WaveModel?> get waves => analyze.waves;

  final List<double> _buffData = [];
  config() {
    start();
    _lisenData = stream.listen((data) {
      _buffData.addAll(data);
    });
  }

  timeClick() {
    if (_buffData.isEmpty) {
      _buffData.addAll(List.filled(kAppTimePeriodic ~/ kMin, 0));
    }
    analyze.insertData(_buffData);
    _buffData.clear();
    notifyListeners();
  }

  start() {
    if (_timer != null) {
      _timer!.cancel();
      _timer = null;
    }

    _timer =
        Timer.periodic(const Duration(milliseconds: kAppTimePeriodic), (timer) {
      timeClick();
    });
  }

  clear() {
    analyze.clear();
  }

  @override
  void dispose() {
    _timer!.cancel();
    _timer = null;
    _lisenData?.cancel();
    _lisenData = null;
    super.dispose();
  }
}

final fatigueProvider = ChangeNotifierProvider((ref) {
  final fatigue = ref.read(faigueBlueProvider);
  final digitalconfig = ref.watch(digitalFilterProvider).fatiguFliter;
  final showFilterConfig = ref.watch(digitalFilterProvider).fatiguShowFliter;
  final setting = ref.watch(dbProvider).fatuigeSetting();
  final mulitpleFilter = MulitpleFilter(setting.multiple!);
  final outlierFilter = OutlierFilter(4095, 0);
  final realFilter = RealFilter(3.3 / 4095);

  final fatiguFliter =
      DigitalFilter(digitalconfig.startFrequency, digitalconfig.endFrequency);
  final showFatiguFliter = DigitalFilter(
      showFilterConfig.startFrequency, showFilterConfig.endFrequency);

  final analyze = FatigueAnalyze(
    minAmplitude: 0.1,
    fliter: [outlierFilter, realFilter, fatiguFliter, mulitpleFilter],
    showFliter: [outlierFilter, realFilter, showFatiguFliter, mulitpleFilter],
  );

  return WaveDataNotifier(fatigue.state, analyze);
});

final sleepProvider = ChangeNotifierProvider((ref) {
  final sleep = ref.read(sleepBlueProvider);

  final digitalconfig = ref.watch(digitalFilterProvider).sleepFliter;
  final showFilterConfig = ref.watch(digitalFilterProvider).fatiguShowFliter;
  final setting = ref.watch(dbProvider).sleepSetting();
  final mulitpleFilter = MulitpleFilter(setting.multiple!);
  final outlierFilter = OutlierFilter(4095, 0);
  final realFilter = RealFilter(3.3 / 4095);
  final fatiguFliter =
      DigitalFilter(digitalconfig.startFrequency, digitalconfig.endFrequency);
  final showFatiguFliter = DigitalFilter(
      showFilterConfig.startFrequency, showFilterConfig.endFrequency);
  final analyze = SleepAnalyze(
    setting.multiple!,
    fliter: [outlierFilter, realFilter, fatiguFliter, mulitpleFilter],
    showFliter: [outlierFilter, realFilter, showFatiguFliter, mulitpleFilter],
  );
  return WaveDataNotifier(sleep.state, analyze);
});

final pulseProvider = ChangeNotifierProvider((ref) {
  final plue = ref.read(plueBlueProvider);
  final digitalconfig = ref.watch(digitalFilterProvider).pulseFliter;
  final showFilterConfig = ref.watch(digitalFilterProvider).fatiguShowFliter;
  final setting = ref.watch(dbProvider).pluseSetting();
  final mulitpleFilter = MulitpleFilter(setting.Multiple!);
  final outlierFilter = OutlierFilter(4095, 0);
  final realFilter = RealFilter(3.3 / 4095);
  final fatiguFliter =
      DigitalFilter(digitalconfig.startFrequency, digitalconfig.endFrequency);
  final showFatiguFliter = DigitalFilter(
      showFilterConfig.startFrequency, showFilterConfig.endFrequency);
  final analyze = pulseAnalyze(
    fliter: [outlierFilter, realFilter, fatiguFliter, mulitpleFilter],
    showFliter: [outlierFilter, realFilter, showFatiguFliter, mulitpleFilter],
  );
  return WaveDataNotifier(plue.state, analyze);
});
